package renderer;

import java.awt.Color;
import java.awt.GraphicsConfigTemplate;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.GraphicsConfigTemplate3D;
import javax.media.j3d.Group;
import javax.media.j3d.LineArray;
import javax.media.j3d.LineAttributes;
import javax.media.j3d.LineStripArray;
import javax.media.j3d.Material;
import javax.media.j3d.Node;
import javax.media.j3d.PointArray;
import javax.media.j3d.PointAttributes;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import kernel.Fiber;
import kernel.FiberSet;

import com.sun.j3d.utils.behaviors.vp.OrbitBehavior;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;

/**
 * Rendering engine for the fiber sets
 *
 */
public class AsuVizRendererCore {

	private static final String BG_LINES = "BG_LINES";
	private static final String BG_POINTS = "BG_POINTS";
	private static final String BG_START_POINTS = "BG_START_POINTS";
	private static final String BG_END_POINTS = "BG_END_POINTS";
	private SimpleUniverse universe;
	private OrbitBehavior orbitBehavior;
	private BranchGroup root;
	private Canvas3D canvas;
	private Map<String, FiberSet> fiberSetIndex;
	
	private BranchGroup groupVolumes;
	private BranchGroup groupFibers;
	private BranchGroup groupROIMatrix;
	private BranchGroup group2DMAtrix;

	public AsuVizRendererCore()
	{
		fiberSetIndex = new HashMap<String, FiberSet>();
		init();
	}
	private void init()
	{
		GraphicsConfigTemplate3D graphicsTemplate = new GraphicsConfigTemplate3D();
		graphicsTemplate.setDepthSize(24);
		graphicsTemplate.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED);
		GraphicsConfiguration conf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(graphicsTemplate);
		canvas = new Canvas3D(conf);
		
		preSetupRender();
	}
	
//	public void startRenderer()
//	{
//		GraphicsConfigTemplate3D graphicsTemplate = new GraphicsConfigTemplate3D();
//		graphicsTemplate.setDepthSize(24);
//		graphicsTemplate.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED);
//		GraphicsConfiguration conf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getBestConfiguration(graphicsTemplate);
//		canvas = new Canvas3D(conf);
//	}

	public void setFiberSetIndex(Map<String, FiberSet> nFiberSet)
	{
		fiberSetIndex = nFiberSet;
	}

	public Canvas3D getCanvas()
	{
		return canvas;
	}

	public void addNewFiberSet(String fiberSetName)
	{
		FiberSet fiberSet = fiberSetIndex.get(fiberSetName);
		BranchGroup bgFibers = new BranchGroup();
		bgFibers.setCapability(Node.ALLOW_BOUNDS_READ);
		bgFibers.setUserData(fiberSet.getName() + "_new");

		ArrayList<Fiber> newFibers = fiberSet.getNewFibers();
		int fiberRenderCount = fiberSet.getFiberRenderCount();
		if(fiberRenderCount == 0)
		{
			fiberRenderCount = newFibers.size();
		}
		BranchGroup bgLines = new BranchGroup();
		bgLines.setUserData(BG_LINES);

		Tube tube = new Tube();
		System.out.println("Rendering new fiber set");
		for(int i = 0; i < fiberRenderCount; i++)
		{
			//			bgLines.addChild(tube.createTube(newFibers.get(i), 0.1, 6, false));
			bgLines.addChild(createFiberLine(newFibers.get(i)));

			bgLines.addChild(tube.createTube(newFibers.get(i), 0.5, 6, false));
			//			bgLines.addChild(createFiberLine(newFibers.get(i)));
		}


		bgFibers.addChild(bgLines);
		root.addChild(bgFibers);
		postSetupRender();
		System.out.println("End Creating BranchGroups");

//		FiberSet newFiberSet = new FiberSet(newFibers);
//		try {
//			File vtkFile = new File(fiberSet.getName() + "_generated.vtk");
//			System.out.println("writing file " + vtkFile.getAbsolutePath());
//			newFiberSet.writeVTKFile(vtkFile);
//			System.out.println("end writing file" + vtkFile.getAbsolutePath());
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
	}

	private void preSetupRender()
	{
		universe = new SimpleUniverse(canvas);
		orbitBehavior = new OrbitBehavior(canvas, OrbitBehavior.REVERSE_ALL | OrbitBehavior.PROPORTIONAL_ZOOM);

		root = new BranchGroup();
		root.setCapability(Node.ALLOW_BOUNDS_READ);
		root.setCapability(Group.ALLOW_CHILDREN_EXTEND);

	}


	private void postSetupRender()
	{
		//		root.addChild(createAxis((BoundingSphere)root.getBounds()));
		//		root.addChild(createAxis((BoundingSphere)root.getBounds()));

		universe.addBranchGraph(root);

		universe.getViewingPlatform().setNominalViewingTransform();

		BoundingSphere boundingSphere = (BoundingSphere) root.getBounds();
		float boundingRadius = (float) boundingSphere.getRadius(); 
		Point3d boundingCenter = new Point3d();
		boundingSphere.getCenter(boundingCenter);

		BoundingSphere bounds = new BoundingSphere(boundingCenter, boundingRadius * 20);
		orbitBehavior.setSchedulingBounds(bounds);

		setLighting(bounds);

		ViewingPlatform viewingPlatform = universe.getViewingPlatform();
		viewingPlatform.setViewPlatformBehavior(orbitBehavior);

		View view = universe.getCanvas().getView();
		view.setBackClipDistance(boundingRadius * 1.5);

		Point3d boundsCenter = new Point3d();
		bounds.getCenter(boundsCenter);


		TransformGroup vpTransformGroup = viewingPlatform.getViewPlatformTransform();
		Transform3D vpTransform3D = new Transform3D();	
		Vector3f transVector = new Vector3f();

		//Get the transformation vector from the transform3d of the transform group
		vpTransformGroup.getTransform(vpTransform3D);   
		vpTransform3D.get(transVector);

		transVector.x = (float) boundsCenter.x;
		transVector.y = (float) boundsCenter.y;
		transVector.z = (float) boundsCenter.z - (boundingRadius * 2.5f);
		vpTransform3D.setTranslation(transVector);
		AxisAngle4f cameraRotationTop = new AxisAngle4f(new Vector3f(0, 1, 0), (float)Math.toRadians(180));
		vpTransform3D.setRotation(cameraRotationTop);

		orbitBehavior.setRotationCenter(boundsCenter);
		orbitBehavior.setHomeTransform(vpTransform3D);
		double cameraDistance = boundsCenter.distance(new Point3d(new double[]{transVector.x, transVector.y, transVector.z}));
		orbitBehavior.setTransFactors(cameraDistance * 0.1, cameraDistance * 0.1);

		orbitBehavior.goHome();
		System.err.println("waiting for renderer to load...");
	}
	public void renderFibers()
	{
		

		for(Map.Entry<String, FiberSet> entry : fiberSetIndex.entrySet())
		{
			FiberSet fiberSet = entry.getValue();
			BranchGroup bgFibers = new BranchGroup();
			bgFibers.setCapability(Node.ALLOW_BOUNDS_READ);
			bgFibers.setUserData(fiberSet.getName());


			double[] minImageBounds = new double[]{-93.062, 93.6125, -46.3256};
			double[] maxImageBounds =new double[]{86.938 , 309.612, 133.674};
			//			bgFibers.addChild(createBoundingBox( minImageBounds, maxImageBounds));
			//			bgFibers.addChild(createBoundingBox(fiberSet));
			//			bgFibers.addChild(createPoint(fiberSet.getFiberSetMin()));
			//			bgFibers.addChild(createPoint(fiberSet.getFiberSetMax()));

			//			bgFibers.addChild(createPoint(minImageBounds, Color.RED));
			//			bgFibers.addChild(createPoint(maxImageBounds, Color.BLUE));

			//			bgFibers.addChild(createBoundingBox( minImageBounds, maxImageBounds));
			//			bgFibers.addChild(createBoundingBox(fiberSet));
			//			bgFibers.addChild(createPoint(fiberSet.getFiberSetMin()));
			//			bgFibers.addChild(createPoint(fiberSet.getFiberSetMax()));

			//			bgFibers.addChild(createPoint(minImageBounds, Color.RED));
			//			bgFibers.addChild(createPoint(maxImageBounds, Color.BLUE));

			boolean[] fiberSetRendering = fiberSet.getRenderSetup();
			ArrayList<Fiber> fibers = fiberSet.getFibers();
			int fiberRenderCount = fiberSet.getFiberRenderCount();
			if(fiberRenderCount == 0)
			{
				fiberRenderCount = fibers.size();
			}
			if(fiberSetRendering[FiberSet.LINE])
			{
				BranchGroup bgLines = new BranchGroup();
				bgLines.setUserData(BG_LINES);


				Tube tube = new Tube();
				int percentage = 0;
				System.out.println("Loading "+ fiberRenderCount+" fibers ");
				for(int i = 0; i < fiberRenderCount; i++)
				{
					//					bgLines.addChild(createFiberLine(fibers.get(i)));
					//					bgLines.addChild(createFiberLine(fibers.get(i)));
					try {
						bgLines.addChild(tube.createTube(fibers.get(i), 0.5, 6, false));
					} catch (Exception e) {
						break;
					}
//					if((i + 1) % (fiberRenderCount/10) == 0)
//					{
//						percentage+=10;
//						System.out.println((i+1) + " fibers out of " + fiberRenderCount + " Added to scenegraph " + percentage + "%");
//					}
				}
				System.out.println("End loading fibers ");

				bgFibers.addChild(bgLines);
			}
			if(fiberSetRendering[FiberSet.POINT])
			{
				BranchGroup bgPoints = new BranchGroup();
				bgPoints.setCapability(Node.ALLOW_BOUNDS_READ);
				bgPoints.setUserData(BG_POINTS);
				for(int i = 0; i < fiberRenderCount; i++)
				{
					bgPoints.addChild(createFiberPoints(fibers.get(i), 10));
				}
				bgFibers.addChild(bgPoints);
			}
			if(fiberSetRendering[FiberSet.START_POINT])
			{
				BranchGroup bgStartPoints = new BranchGroup();
				bgStartPoints.setCapability(Node.ALLOW_BOUNDS_READ);
				bgStartPoints.setUserData(BG_START_POINTS);
				for(int i = 0; i < fiberRenderCount; i++)
				{
					bgStartPoints.addChild(createFiberStartPoints(fibers.get(i), 10));
				}
				bgFibers.addChild(bgStartPoints);
			}
			if(fiberSetRendering[FiberSet.END_POINT])
			{
				BranchGroup bgEndPoints = new BranchGroup();
				bgEndPoints.setCapability(Node.ALLOW_BOUNDS_READ);
				bgEndPoints.setUserData(BG_END_POINTS);
				for(int i = 0; i < fiberRenderCount; i++)
				{
					bgEndPoints.addChild(createFiberEndPoints(fibers.get(i), 10));
				}
				bgFibers.addChild(bgEndPoints);
			}		
			root.addChild(bgFibers);
		}


		postSetupRender();
	}

	private void setLighting(BoundingSphere bounds)
	{
		BranchGroup lightGroup = new BranchGroup();


		Color3f light1Color = new Color3f(1f, 1f, 1f);
		Vector3f light1Direction = new Vector3f(1.0f, 0.0f, -1.0f);
		DirectionalLight light1 = new DirectionalLight(light1Color, light1Direction);
		light1.setInfluencingBounds(bounds);
		light1.setCapability(Node.ALLOW_BOUNDS_READ);

		lightGroup.addChild(light1);

		Vector3f light2Direction = new Vector3f(1.0f, 0.0f, 1.0f);
		DirectionalLight light2 = new DirectionalLight(light1Color, light2Direction);
		light2.setInfluencingBounds(bounds);
		light2.setCapability(Node.ALLOW_BOUNDS_READ);

		lightGroup.addChild(light2);

		Color3f ambientLightColor = new Color3f(0.2f, 0.2f, 0.2f);
		AmbientLight ambientLight = new AmbientLight(ambientLightColor);
		ambientLight.setInfluencingBounds(bounds);
		ambientLight.setCapability(Node.ALLOW_BOUNDS_READ);

		lightGroup.addChild(ambientLight);


		root.addChild(lightGroup);
	}

	private BranchGroup createAxis(BoundingSphere bsphere)
	{
		float bsRadius = (float) bsphere.getRadius();
		Point3d bsCenter = new Point3d();
		bsphere.getCenter(bsCenter);

		BranchGroup axisBG = new BranchGroup();
		TransformGroup axis = new TransformGroup();
		Transform3D transform = new Transform3D();
		axis.setTransform(transform);

		//		Appearance sphereApp = new Appearance();
		//		PolygonAttributes patt = new PolygonAttributes();
		//		patt.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		//		sphereApp.setPolygonAttributes(patt);
		//		Sphere sphere = new Sphere(bsRadius, sphereApp);
		//		axisBG.addChild(sphere);

		Color3f red = new Color3f(1, 0, 0);
		Color3f green = new Color3f(0, 1, 0);
		Color3f blue = new Color3f(0, 0, 1);

		Appearance appRed = new Appearance();
		ColoringAttributes ca = new ColoringAttributes(red, ColoringAttributes.SHADE_FLAT);
		appRed.setColoringAttributes(ca);

		Point3f[] xAxisPts = new Point3f[2];
		xAxisPts[0] = new Point3f((float)bsCenter.x, (float)bsCenter.y, (float)bsCenter.z);
		xAxisPts[1] = new Point3f((float)bsCenter.x + bsRadius, (float)bsCenter.y, (float)bsCenter.z);
		LineArray xAxisLine = new LineArray(2, LineArray.COORDINATES);
		xAxisLine.setCoordinates(0, xAxisPts);
		Shape3D xAxis = new Shape3D(xAxisLine, appRed);
		xAxis.setUserData("X Axis");
		axis.addChild(xAxis);

		Appearance appGreen = new Appearance();
		ColoringAttributes cag = new ColoringAttributes(green,
				ColoringAttributes.SHADE_FLAT);
		appGreen.setColoringAttributes(cag);

		Point3f[] yAxisPts = new Point3f[2];
		yAxisPts[0] = new Point3f((float)bsCenter.x, (float)bsCenter.y, (float)bsCenter.z);
		yAxisPts[1] = new Point3f((float)bsCenter.x, (float)bsCenter.y+ bsRadius, (float)bsCenter.z);
		LineArray yAxisLine = new LineArray(2, LineArray.COORDINATES);
		yAxisLine.setCoordinates(0, yAxisPts);
		Shape3D yAxis = new Shape3D(yAxisLine, appGreen);
		yAxis.setUserData("Y Axis");
		axis.addChild(yAxis);

		Appearance appBlue = new Appearance();
		ColoringAttributes cab = new ColoringAttributes(blue,
				ColoringAttributes.SHADE_FLAT);
		appBlue.setColoringAttributes(cab);

		Point3f[] zAxisPts = new Point3f[2];
		zAxisPts[0] = new Point3f((float)bsCenter.x, (float)bsCenter.y, (float)bsCenter.z);
		zAxisPts[1] = new Point3f((float)bsCenter.x, (float)bsCenter.y, (float)bsCenter.z+ bsRadius);
		LineArray zAxisLine = new LineArray(2, LineArray.COORDINATES);
		zAxisLine.setCoordinates(0, zAxisPts);
		Shape3D zAxis = new Shape3D(zAxisLine, appBlue);
		zAxis.setUserData("Z Axis");
		axis.addChild(zAxis);

		axisBG.addChild(axis);

		return axisBG;
	}




	private BranchGroup createFiberLine(Fiber fiber)
	{
		ArrayList<double[]> points = fiber.getPoints();
		Color fiberColor = fiber.getFiberColor();

		BranchGroup fiberLine = new BranchGroup();
		fiberLine.setCapability(Node.ALLOW_BOUNDS_READ);
		fiberLine.setUserData(fiber);

		if(points.size() > 1)
		{
			int[] lineStripCount = new int[1];
			lineStripCount[0] = points.size();



			LineStripArray geometryRaw = new LineStripArray(points.size(), LineArray.COORDINATES, lineStripCount);

			for(int i = 0; i < points.size(); i ++)
			{
				double[] p = points.get(i);
				((LineStripArray)geometryRaw).setCoordinate(i, new Point3d(p));
			}

			Appearance appearance = new Appearance();
			ColoringAttributes colAtt = new ColoringAttributes();
			colAtt.setColor(new Color3f(fiberColor));
			appearance.setColoringAttributes(colAtt);

			LineAttributes lAtt = new LineAttributes();
			//			lAtt.setLineWidth(10);
			lAtt.setLineAntialiasingEnable(true);
			appearance.setLineAttributes(lAtt);

			Shape3D geometry = new Shape3D(geometryRaw, appearance);	
			fiberLine.addChild(geometry);
			//			fiberBG.addChild(fiberLine);
		}

		return fiberLine;
	}

	private BranchGroup createFiberPoints(Fiber fiber, int pointSize)
	{
		ArrayList<double[]> points = fiber.getPoints();
		Color fiberColor = fiber.getFiberColor();
		BranchGroup fiberPoints = new BranchGroup();
		fiberPoints.setCapability(Node.ALLOW_BOUNDS_READ);
		fiberPoints.setUserData(fiber);

		if(points.size() > 0)
		{
			PointArray geometryRaw = new PointArray(points.size() , PointArray.COORDINATES);
			for(int i = 0; i < points.size(); i ++)
			{
				double[] p = points.get(i);
				((PointArray)geometryRaw).setCoordinate(i, new Point3d(p));
			}

			Appearance appearance = new Appearance();
			ColoringAttributes colAtt = new ColoringAttributes();
			colAtt.setColor(new Color3f(fiberColor));
			appearance.setColoringAttributes(colAtt);

			PointAttributes pointAtt = new PointAttributes(pointSize, true);
			appearance.setPointAttributes(pointAtt);

			Shape3D geometry = new Shape3D(geometryRaw, appearance);	

			fiberPoints.addChild(geometry);
		}

		return fiberPoints;
	}


	private BranchGroup createFiberStartPoints(Fiber fiber, int pointSize)
	{
		ArrayList<double[]> points = fiber.getPoints();

		BranchGroup startPoints = new BranchGroup();
		startPoints.setCapability(Node.ALLOW_BOUNDS_READ);
		startPoints.setUserData(fiber);

		if(points.size() > 1)
		{
			PointArray geometryRaw = new PointArray(points.size() , PointArray.COORDINATES);

			double[] p = points.get(0);
			((PointArray)geometryRaw).setCoordinate(pointSize, new Point3d(p));


			Appearance appearance = new Appearance();
			ColoringAttributes colAtt = new ColoringAttributes();
			colAtt.setColor(new Color3f(Color.GREEN));
			appearance.setColoringAttributes(colAtt);

			PointAttributes pointAtt = new PointAttributes(pointSize, true);
			appearance.setPointAttributes(pointAtt);

			Shape3D geometry = new Shape3D(geometryRaw, appearance);	

			startPoints.addChild(geometry);

		}

		return startPoints;
	}

	private BranchGroup createFiberEndPoints(Fiber fiber, int pointSize)
	{
		ArrayList<double[]> points = fiber.getPoints();
		BranchGroup	endPoints = new BranchGroup();
		endPoints.setCapability(Node.ALLOW_BOUNDS_READ);
		endPoints.setUserData(fiber);

		if(points.size() > 1)
		{
			PointArray geometryRaw = new PointArray(points.size() , PointArray.COORDINATES);

			double[] p = points.get(points.size() - 1);
			((PointArray)geometryRaw).setCoordinate(0, new Point3d(p));


			Appearance appearance = new Appearance();
			ColoringAttributes colAtt = new ColoringAttributes();
			colAtt.setColor(new Color3f(Color.RED));
			appearance.setColoringAttributes(colAtt);

			PointAttributes pointAtt = new PointAttributes(pointSize, true);
			appearance.setPointAttributes(pointAtt);

			Shape3D geometry = new Shape3D(geometryRaw, appearance);	

			endPoints.addChild(geometry);
		}

		return endPoints;
	}

	private BranchGroup createBoundingBox(FiberSet fiberSet)
	{
		Appearance appearance = new Appearance();
		PolygonAttributes pAtt = new PolygonAttributes();
		pAtt.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		ColoringAttributes colAtt = new ColoringAttributes();
		colAtt.setColor(new Color3f(Color.WHITE));
		appearance.setPolygonAttributes(pAtt);
		appearance.setColoringAttributes(colAtt);

		Box box = new Box((float)fiberSet.getWidth(), (float)fiberSet.getHeight(), (float)fiberSet.getDepth(), Box.GEOMETRY_NOT_SHARED | Box.GENERATE_NORMALS, appearance);

		BranchGroup boxBg = new BranchGroup();
		TransformGroup boxTg = new TransformGroup();
		Transform3D boxt3d = new Transform3D();
		boxt3d.setTranslation(new Vector3d(fiberSet.getCenter()));
		boxTg.setTransform(boxt3d);
		boxTg.addChild(box);

		boxBg.addChild(boxTg);

		return boxBg;
	}

	private BranchGroup createBoundingBox(double[] minBounding, double[] maxBounding)
	{
		Appearance appearance = new Appearance();
		PolygonAttributes pAtt = new PolygonAttributes();
		pAtt.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		ColoringAttributes colAtt = new ColoringAttributes();
		colAtt.setColor(new Color3f(Color.WHITE));
		appearance.setPolygonAttributes(pAtt);
		appearance.setColoringAttributes(colAtt);

		double width = (maxBounding[0] - minBounding[0])/2;
		double height = (maxBounding[1] - minBounding[1])/2;
		double depth = (maxBounding[2] - minBounding[2])/2;

		Box box = new Box((float)width, (float)height, (float)depth, Box.GEOMETRY_NOT_SHARED | Box.GENERATE_NORMALS, appearance);

		BranchGroup boxBg = new BranchGroup();
		TransformGroup boxTg = new TransformGroup();
		Transform3D boxt3d = new Transform3D();
		boxt3d.setTranslation(new Vector3d(minBounding[0] + width, minBounding[1] + height, minBounding[2] + depth));
		boxTg.setTransform(boxt3d);
		boxTg.addChild(box);

		boxBg.addChild(boxTg);

		return boxBg;
	}

	private BranchGroup createPoint(double[] point, Color color)
	{
		Appearance appearance = new Appearance();
		ColoringAttributes colAtt = new ColoringAttributes();
		colAtt.setColor(new Color3f(color));
		PointAttributes pAtt = new PointAttributes();
		pAtt.setPointSize(3);
		appearance.setColoringAttributes(colAtt);
		appearance.setPointAttributes(pAtt);

		PointArray pArray = new PointArray(1, PointArray.COORDINATES);
		pArray.setCoordinate(0, new Point3d(point));
		Shape3D pS3d = new Shape3D(pArray, appearance);

		BranchGroup bg = new BranchGroup();
		bg.addChild(pS3d);
		return bg;
	}

	public void renderRoiIntegerMatrix(int[][][] roiMatrix, int max)
	{
//		preSetupRender();
		BranchGroup roiMatrixBg = new BranchGroup();

		Appearance appearanceGreen = new Appearance();
		PolygonAttributes pAtt = new PolygonAttributes();
		pAtt.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		appearanceGreen.setPolygonAttributes(pAtt);
		Material matGreen = new Material();
		matGreen.setDiffuseColor(new Color3f(Color.GREEN));
		appearanceGreen.setMaterial(matGreen);

		Appearance appearanceYellow = new Appearance();
		Material matYellow = new Material();
		matYellow.setDiffuseColor(new Color3f(Color.YELLOW));
		appearanceYellow.setMaterial(matYellow);

		Appearance appearanceRed = new Appearance();
		Material matRed = new Material();
		matRed.setDiffuseColor(new Color3f(Color.RED));
		appearanceRed.setMaterial(matRed);

		int counterGreen = 0;
		int counterYellow = 0;
		int counterRed = 0;

		int boundaryStep = (int) max/3;

		for(int i = 0; i < roiMatrix.length; i ++)
		{
			for(int j = 0; j < roiMatrix[0].length; j ++)
			{
				for(int k = 0; k < roiMatrix[0][0].length; k ++)
				{
					if(roiMatrix[i][j][k] != 0)
					{
						TransformGroup boxTg = new TransformGroup();
						Transform3D boxt3d = new Transform3D();
						boxt3d.setTranslation(new Vector3d(i * 5, j * 5 , k * 5));
						boxTg.setTransform(boxt3d);

						if(roiMatrix[i][j][k] < boundaryStep)
						{
							Box box = new Box(2.5f, 2.5f, 2.5f, Box.GEOMETRY_NOT_SHARED | Box.GENERATE_NORMALS, appearanceGreen);
							boxTg.addChild(box);
							counterGreen++;
						}
						else if(roiMatrix[i][j][k] >= boundaryStep && roiMatrix[i][j][k] < (boundaryStep * 2))
						{
							Box box = new Box(2.5f, 2.5f, 2.5f, Box.GEOMETRY_NOT_SHARED | Box.GENERATE_NORMALS, appearanceYellow);
							boxTg.addChild(box);
							counterYellow++;
						}
						else
						{
							Box box = new Box(2.5f, 2.5f, 2.5f, Box.GEOMETRY_NOT_SHARED | Box.GENERATE_NORMALS, appearanceRed);
							boxTg.addChild(box);
							counterRed++;
						}

						roiMatrixBg.addChild(boxTg);
					}
				}
			}
		}

		System.out.println("Max: " + max);
		System.out.println("Green " + counterGreen);
		System.out.println("Yellow " + counterYellow);
		System.out.println("Red " + counterRed);
		root.addChild(roiMatrixBg);

		postSetupRender();
	}

	public void renderRoiInteger2DMatrix(int[][] roiMatrix, int max)
	{
		System.out.println("Rendering 2D Matrix");
//		preSetupRender();
		BranchGroup roiMatrixBg = new BranchGroup();

		int counterGreen = 0;
		int counterYellow = 0;
		int counterRed = 0;

		int boundaryStep = (int) max/3;

		for(int i = 0; i < roiMatrix.length; i ++)
		{
			for(int j = 0; j < roiMatrix[0].length; j ++)
			{
				if(roiMatrix[i][j] != 0)
				{
					if(roiMatrix[i][j] < boundaryStep)
					{
						roiMatrixBg.addChild(createPoint(new double[]{i * 2, j * 2 , 0}, Color.GREEN));
						counterGreen++;
					}
					else if(roiMatrix[i][j] >= boundaryStep && roiMatrix[i][j] < (boundaryStep * 2))
					{
						roiMatrixBg.addChild(createPoint(new double[]{i * 2, j * 2 , 0}, Color.YELLOW));
						counterYellow++;
					}
					else
					{
						roiMatrixBg.addChild(createPoint(new double[]{i * 2, j * 2 , 0}, Color.RED));
						counterRed++;
					}
				}
				//				else
				//				{
				//					roiMatrixBg.addChild(createPoint(new double[]{i * 2, j * 2 , 0}, Color.BLUE));
				//				}
			}
		}

		System.out.println("BStep: " + boundaryStep);
		System.out.println("Green " + counterGreen);
		System.out.println("Yellow " + counterYellow);
		System.out.println("Red " + counterRed);
		root.addChild(roiMatrixBg);

		postSetupRender();
	}
}


